package doc

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
)

const (
	SuccessCode="000000"

)

type (

	//响应
	Resp struct {
		Type string `json:"type"`
		StatusCode string `json:"statusCode"`
	}

	//documentInfo
	DocumentInfo struct {
		DocumentID int `json:"documentID"`
		Content string `json:"content"`
		ContentRaw string `json:"contentRaw"`
		ContentType int `json:"contentType"`
		GroupID int `json:"groupID"`
		ProjectID int `json:"projectID"`
		Title string `json:"title"`
	}
	//documentList
	DocumentListAck struct {
		Resp
		DocumentList []DocumentInfo `json:"documentList"`
	}



	EoLinker struct {
		Address string
		PHPSESSID string //认证数据

		ProjectId int //项目id
		GroupId int //分组id
	}
)



func NewEoLinker(address string,PHPSESSID string,projectId int) *EoLinker {
	this := new(EoLinker)
	this.Address=address
	this.PHPSESSID=PHPSESSID
	this.ProjectId=projectId
	return this
}

func (this *EoLinker)SetGroupId(id int) *EoLinker {
	this.GroupId=id
	return this
}

func (this *EoLinker) httpPost(targetUrl string,postData interface{}) (bodyByte []byte,err error) {
	var (
		postStr  url.Values
		postParams map[string]interface{}

		cookieJar *cookiejar.Jar
		req       *http.Request
		resp      *http.Response

	)
	if postParams,err=Struct2Map(postData);err!= nil {
		return
	}

	postStr=url.Values{}
	for k,v:=range postParams {
		postStr.Add(k,fmt.Sprintf("%v",v))
	}


	tr := &http.Transport{
		DisableKeepAlives: true,                                  //禁用长连接
		TLSClientConfig:   &tls.Config{InsecureSkipVerify: true}, //跳过证书验证
	}
	//http cookie接口
	if cookieJar, err = cookiejar.New(nil); err != nil {
		return
	}

	client := &http.Client{
		Jar:       cookieJar,
		Transport: tr,
	}


	if req, err = http.NewRequest("POST", targetUrl, strings.NewReader(postStr.Encode())); err != nil {
		return
	}

	req.Header.Set("Connection", "close")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")


	req.AddCookie(&http.Cookie{
		Name:       "PHPSESSID",
		Value:      this.PHPSESSID,
	})

	if resp, err = client.Do(req); err != nil {
		return
	}
	resp.Header.Set("Connection", "close")
	defer resp.Body.Close()

	if bodyByte, err = ioutil.ReadAll(resp.Body); err != nil {
		return
	}

	return

}

//编辑文档
func (this *EoLinker)EditDocument(doc DocumentInfo) (err error) {
	var (
		ack Resp
		res []byte
	)

	if res,err=this.httpPost(fmt.Sprintf("http://%s/server/index.php?g=Web&c=Document&o=editDocument",this.Address),doc);err!= nil {
		return
	}

	if err=json.Unmarshal(res,&ack);err!= nil {
		return
	}
	if err=CheckCode(ack.StatusCode);err!= nil {
		if ack.StatusCode== "230000" {
			err=nil
			return
		}
		return
	}

	return

}

//添加文档
func (this *EoLinker)AddDocument(doc DocumentInfo)(err error)  {

	var (
		ack Resp
		res []byte
	)
	url:=fmt.Sprintf("http://%s/server/index.php?g=Web&c=Document&o=addDocument",this.Address)

	if res,err=this.httpPost(url,doc);err!= nil {
		return
	}

	if err=json.Unmarshal(res,&ack);err!= nil {
		return
	}
	if err=CheckCode(ack.StatusCode);err!= nil {
		return
	}

	return

}

//保存文档
func (this *EoLinker)SaveDocument(title string,groupId int,content string) (err error) {
	var (
		doc DocumentInfo
	)

	title=strings.Trim(title," ")
	if title== "" {
		return errors.New("标题缺失")
	}

	if doc,err=this.DocumentInfo(title);err!= nil {
		return
	}
	if groupId> 0 {
		doc.GroupID=groupId
	}

	doc.Title=title
	doc.ContentRaw=content

	doc.ContentType=1



	if doc.DocumentID== 0 {
		//新增
		if err=this.AddDocument(doc);err!= nil {
			return
		}

		if doc,err=this.DocumentInfo(title);err!= nil {
			return
		}else{
			if doc.DocumentID== 0 {
				err=fmt.Errorf("添加{%s}出现问题,请检查",title)
				return
			}
		}
	}

	//修改content
	doc.Content=fmt.Sprintf(`<p><a href="http://%s/#/home/project/inside/doc/edit?groupID=%d&amp;documentID=%d&amp;projectID=%d">文档已更新,查看保存确认</a></p>`,this.Address,doc.GroupID,doc.DocumentID,doc.ProjectID)

	//编辑
	err=this.EditDocument(doc)
	return

}

//获取单个文档
func (this *EoLinker) DocumentInfo(title string)  (doc DocumentInfo,err error){
	var (
		list DocumentListAck
		res []byte
	)

	if res,err=this.httpPost(fmt.Sprintf("http://%s/server/index.php?g=Web&c=Document&o=searchDocument",this.Address),map[string]interface{}{
		"projectID":this.ProjectId,
		"groupID":-1,
		"tips":title,
	});err!= nil {
		return
	}

	if err=json.Unmarshal(res,&list);err!= nil {
		return
	}
	if err=CheckCode(list.StatusCode);err!= nil {
		if list.StatusCode== "230000" {
			err=nil
		}
		return
	}

	//JsonPrint(list.DocumentList)
	if len(list.DocumentList)> 0 {

		for _,v:=range list.DocumentList {
			if v.Title== title {
				doc=v
				return
			}
		}

	}

	return
}



func Struct2Map(s interface{}) (m map[string]interface{},err error) {
	var sc []byte

	if s == nil {
		return
	}
	m=make(map[string]interface{})

	if sc,err=json.Marshal(s);err!= nil {
		return
	}

	err=json.Unmarshal(sc,&m)
	return
}

func CheckCode(code string) error {
	if code!= SuccessCode {
		return fmt.Errorf("错误码:%s",code)
	}

	return nil

}

//json方式打印结构体
func JsonPrint(obj interface{}) {
	tmp, _ := json.MarshalIndent(obj, "", "     ")
	fmt.Println(string(tmp))
}


